package files

//获取本地文件夹信息
import (
	"bytes"
	"fmt"
	"net"
	"os"
	"path/filepath"
	"time"

	"gitcode.com/shexk/naserver/core"
	x "gitee.com/shexk/gtl/net"
	"gitee.com/shexk/gtl/protocol"
)

func GetID() uint64 {
	return uint64(time.Now().UnixNano()) //time.Now().UnixMilli()
}

type RequestCmd struct {
	CMDName string //请求的操作命令
	Value   string //请求的值
}

type FileInfo struct {
	IsDir    bool
	FilePath string
	FileSize uint64
}

func NewFileInfo(filepath string, isdir bool, size uint64) *FileInfo {
	return &FileInfo{FilePath: filepath, IsDir: isdir, FileSize: size}
}

type SearchFile struct {
	Dir string
}

func NewSearchFile(dir string) *SearchFile {
	return &SearchFile{Dir: dir}
}

type TransFileInfo struct {
	Command  string
	Dir      string
	FileName []string
	Number   uint32
	BDir     []byte
	Length   []uint64
}
type DownloadFileInfo struct {
	Command  string
	FileName string
	Flag     byte
	ID       uint64
	Length   uint64
	Index    uint32
	Data     []byte
	Crc      uint16
}

func (c *SearchFile) GetDirInfo() []byte {
	result := core.NewList[*FileInfo]()
	// 读取目录内容
	entries, err := os.ReadDir(c.Dir)
	if err != nil { //为空文件夹
		info := TransFileInfo{Command: "GetDir", Dir: c.Dir}
		bufs, _ := protocol.GetBytesFromStruct(info)

		return bufs
	}
	// 递归处理每个子项
	for _, entry := range entries {
		childPath := filepath.Join(c.Dir, entry.Name())
		isDir := false
		var fileSize uint64 = 0
		fileInfo, err := os.Stat(childPath)
		if err == nil {
			// 判断是否为正常文件
			if fileInfo.Mode().IsRegular() {
				fileSize = uint64(fileInfo.Size())
			}
			if fileInfo.Mode().IsDir() {
				isDir = true
			}
		}
		if isDir {
			result.Append(NewFileInfo(childPath, true, 0))
		} else {
			result.Append(NewFileInfo(childPath, false, fileSize))
		}
	}
	return c.getByteFromDirs(result.ToSlice())
}

func (c *SearchFile) getByteFromDirs(dirs []*FileInfo) []byte {
	var info = TransFileInfo{}
	info.Command = "GetDir"
	info.Dir = c.Dir
	info.Number = uint32(len(dirs))

	ll := len(dirs)
	info.BDir = make([]byte, ll)
	info.FileName = make([]string, ll)
	info.Length = make([]uint64, ll)

	for index := range dirs {
		dir := dirs[index]
		if dir.IsDir {
			info.BDir[index] = 0x01
		} else {
			info.BDir[index] = 0x00
		}
		info.FileName[index] = dir.FilePath
		info.Length[index] = dir.FileSize
	}
	bufs, _ := protocol.GetBytesFromStruct(info)
	return bufs
}

func DownloadFile(filepath string, conn net.Conn) {
	id := GetID()
	crc := core.NewCRC16()
	file, err := os.Open(filepath)
	if err != nil {
		return //fmt.Errorf("无法打开文件: %w", err)
	}
	defer file.Close()

	beginTime := time.Now().Local().UnixMilli()
	//发送头部

	info := DownloadFileInfo{}

	info.Command = "Download"
	info.Flag = 0x00
	info.ID = id
	info.FileName = filepath

	if fileinfo, err1 := file.Stat(); err1 == nil {
		if fileinfo.Mode().IsRegular() {
			info.Length = uint64(fileinfo.Size())
		} else {
			info.Length = 0
		}
	} else {
		info.Length = 0
	}
	bufs, _ := protocol.GetBytesFromStruct(info)
	ss := bytes.NewBuffer(nil)
	ss.WriteByte(0x04)
	ss.Write(bufs)
	x.WritePackage(conn, ss.Bytes())

	buffer := make([]byte, core.GetConfig().DownBlockSize)
	chunkNumber := 0

	for {
		info.Flag = 0x01

		// 读取一块数据
		n, err := file.Read(buffer)
		if err != nil {
			if err.Error() == "EOF" {
				// 已经读取到文件末尾
				break
			}
			return //fmt.Errorf("读取文件时发生错误: %w", err)
		}
		chunkNumber++
		crc.Calc(buffer[0:n])

		// 处理当前块的数据 (buffer[0:n])
		info.Index = uint32(chunkNumber)
		info.Data = buffer[0:n]

		buf, _ := protocol.GetBytesFromStruct(info)

		ss := bytes.NewBuffer(nil)
		ss.WriteByte(0x04)
		ss.Write(buf)

		x.WritePackage(conn, ss.Bytes())
	}
	//发送尾部
	info.Flag = 0x02

	info.Data = nil
	info.Index = 0
	info.Crc = crc.Value

	buf2, _ := protocol.GetBytesFromStruct(info)
	sss := bytes.NewBuffer(nil)
	sss.WriteByte(0x04)
	sss.Write(buf2)
	x.WritePackage(conn, sss.Bytes())
	endTime := time.Now().Local().UnixMilli()
	fmt.Println("Trans File Name=", filepath, "ChunkNum=", chunkNumber, "Time=", endTime-beginTime)
}
